package com.airbnb.lottie.parser;

import com.airbnb.lottie.parser.moshi.JsonReader;
import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.model.animatable.AnimatableColorValue;
import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
import com.airbnb.lottie.model.animatable.AnimatableIntegerValue;
import com.airbnb.lottie.model.content.ShapeStroke;
import com.airbnb.lottie.value.Keyframe;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class ShapeStrokeParser {

    private static JsonReader.Options NAMES = JsonReader.Options.of("nm", "c", "w", "o", "lc", "lj", "ml", "hd", "d");

    private static final JsonReader.Options DASH_PATTERN_NAMES = JsonReader.Options.of("n", "v");

    private ShapeStrokeParser() {
    }

    static ShapeStroke parse(JsonReader reader, LottieComposition composition) throws IOException {
        String name = null;
        AnimatableColorValue color = null;
        AnimatableFloatValue width = null;
        AnimatableIntegerValue opacity = null;
        ShapeStroke.LineCapType capType = null;
        ShapeStroke.LineJoinType joinType = null;
        AnimatableFloatValue offset = null;
        float miterLimit = 0f;
        boolean hidden = false;

        List<AnimatableFloatValue> lineDashPattern = new ArrayList<>();

        while (reader.hasNext()) {
            switch (reader.selectName(NAMES)) {
                case 0:
                    name = reader.nextString();
                    break;
                case 1:
                    color = AnimatableValueParser.parseColor(reader, composition);
                    break;
                case 2:
                    width = AnimatableValueParser.parseFloat(reader, composition);
                    break;
                case 3:
                    opacity = AnimatableValueParser.parseInteger(reader, composition);
                    break;
                case 4:
                    capType = ShapeStroke.LineCapType.values()[reader.nextInt() - 1];
                    break;
                case 5:
                    joinType = ShapeStroke.LineJoinType.values()[reader.nextInt() - 1];
                    break;
                case 6:
                    miterLimit = (float) reader.nextDouble();
                    break;
                case 7:
                    hidden = reader.nextBoolean();
                    break;
                case 8:
                    reader.beginArray();
                    while (reader.hasNext()) {
                        String n = null;
                        AnimatableFloatValue val = null;

                        reader.beginObject();
                        while (reader.hasNext()) {
                            switch (reader.selectName(DASH_PATTERN_NAMES)) {
                                case 0:
                                    n = reader.nextString();
                                    break;
                                case 1:
                                    val = AnimatableValueParser.parseFloat(reader, composition);
                                    break;
                                default:
                                    reader.skipName();
                                    reader.skipValue();
                            }
                        }
                        reader.endObject();

                        switch (n) {
                            case "o":
                                offset = val;
                                break;
                            case "d":
                            case "g":
                                composition.setHasDashPattern(true);
                                lineDashPattern.add(val);
                                break;
                        }
                    }
                    reader.endArray();

                    if (lineDashPattern.size() == 1) {
                        // If there is only 1 value then it is assumed to be equal parts on and off.
                        lineDashPattern.add(lineDashPattern.get(0));
                    }
                    break;
                default:
                    reader.skipValue();
            }
        }

        // Telegram sometimes omits opacity.
        opacity = opacity == null ? new AnimatableIntegerValue(Collections.singletonList(new Keyframe<>(100))) : opacity;
        return new ShapeStroke(name, offset, lineDashPattern, color, opacity, width, capType, joinType, miterLimit,
            hidden);
    }
}
